package com.superbit.service.user.impl;

import java.text.ParseException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.transaction.Transactional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.superbit.core.constant.UserStatusConstant;
import com.superbit.core.entry.UserActivityInfo;
import com.superbit.core.entry.UserBaseInfo;
import com.superbit.core.entry.UserSafeInfo;
import com.superbit.core.exception.BusinessException;
import com.superbit.core.service.LongTimeTaskCallback;
import com.superbit.core.service.RegisterService;
import com.superbit.service.match.impl.TradeLogServiceImpl;
import com.superbit.service.user.daodefine.AppConfigDao;
import com.superbit.service.user.daodefine.UserActivityInfoDao;
import com.superbit.service.user.daodefine.UserBaseInfoDao;
import com.superbit.service.user.daodefine.UserRedisDao;
import com.superbit.service.user.daodefine.UserSafeInfoDao;
import com.superbit.service.util.CommonUtils;
import com.superbit.utils.constantutil.CollectionUtils;
import com.superbit.utils.constantutil.FixedTime;
import com.superbit.utils.dbutil.RedisKeyUtils;
import com.superbit.utils.mailutil.EmailFailException;
import com.superbit.utils.mailutil.EmailSendService;
import com.superbit.utils.mobileutil.MobileMessService;


import net.sf.json.JSONObject;

/** @author  WangZhenwei 
  * @date 创建时间：2018年1月5日 下午5:26:09  
  * @descrip 注册的业务层实现
  */
@Service
public class RegisterServiceImpl implements RegisterService{
	
	private static Logger log = LoggerFactory.getLogger(RegisterServiceImpl.class);
				
	@Autowired
	private UserRedisDao userRedisDao;
	
	@Autowired
	private UserBaseInfoDao userBaseInfoDao;
	
	@Autowired
	private UserSafeInfoDao userSafeInfoDao;
	
	@Autowired
	private UserActivityInfoDao userActivityInfoDao;
	
	@Autowired
	private LongTimeCallback longTimeCallback;
	
	@Autowired
	private AppConfigDao appConfigDao;
	
	@Autowired
	private MobileMessService mobileMessService;
	
	@Autowired
	private EmailSendService emailSendService;
	
	private Logger logger;

	@SuppressWarnings("unused")
	private String password;
	
	private int phoneMessageVerifyLimit;
	
	private int phoneMessageSendLimit;
	
	private int emailMessageVerifyLimit;
	
	private int emailMessageSendLimit;
	
//	@Value("${ctx}")
	private String ctx;
	
	@PostConstruct
	private void init(){
		logger = LoggerFactory.getLogger(this.getClass());
		phoneMessageSendLimit = appConfigDao.getAppConfigIntValue("phoneMessageSendLimit", 5);
		phoneMessageVerifyLimit = appConfigDao.getAppConfigIntValue("phoneMessageVerifyLimit", 5);
		emailMessageSendLimit = appConfigDao.getAppConfigIntValue("emailMessageSendLimit", 5);
		emailMessageVerifyLimit = appConfigDao.getAppConfigIntValue("emailMessageVerifyLimit", 5);
	}

	/**
	 * 手机注册
	 * 
	 */
	@Override
	public void phoneRegister(String areaCode, String phone) throws BusinessException {
		// 1.根据手机号统计使用该手机号注册的人数
		int count = userBaseInfoDao.countUserByPhone(phone);
		if(count > 0){
			throw new BusinessException("US652","The phone has been used!",null);
		}
		// 2.验证用户输入的验证码（错误给提示、超过限制次数）
		Map<String,String> tempInfo = userRedisDao.getPhoneRegisterTempInfo(phone);
		  // 手机发送次数限制为5次
		if(null==tempInfo || tempInfo.isEmpty()||Integer.parseInt(tempInfo.get("phoneMessageSendCount")+"") < phoneMessageSendLimit){   // 待优化
			int phoneMessageSendCount = 0;
			// 手机注册的临时信息存在
			if(null != tempInfo && !tempInfo.isEmpty()){
				phoneMessageSendCount  = Integer.parseInt(tempInfo.get("phoneMessageSendCount")+"");
			}else{
				tempInfo  = new HashMap<String,String>();
			}
			
			// 生成六位随机数的验证码
			String captcha = CommonUtils.randCode("", UserStatusConstant.CHECK_CODE_LENGTH);
			// 发送短信验证码
			//this.sendMessage(areaCode, phone, 1, 1, "activeMobile", CollectionUtils.buildMap("code", captcha), true);
			mobileMessService.sendMessage(phone, "phoneRegister", true, CollectionUtils.buildMap("code", captcha));
			//this.sendMessage(areaCode, phone, 1, 1, "");
			
			tempInfo.put("areaCode", areaCode);
			tempInfo.put("phone", phone);
			tempInfo.put("captcha", captcha);
			tempInfo.put("phoneMessageSendCount", phoneMessageSendCount + 1 + "");
			tempInfo.put("phoneMessageVerifyCount", "0");
			tempInfo.put("phoneMessageSendTime", System.currentTimeMillis()+"");
			// 保存手机注册的临时信息到redis数据库中
			userRedisDao.savePhoneRegisterTempInfo(tempInfo);
		}else {
			log.error("US602", "Phone message delivery exceeds Limit");
			throw new BusinessException("US602", "Phone message delivery exceeds " 
					+ phoneMessageSendLimit + " limit!", null);
		}
				
	}

	/**
	 * 手机注册激活
	 * @throws ParseException 
	 * 
	 */
	@Transactional
	@Override
	public Map<String, Object> activePhone(String phone, String captcha, String password) throws BusinessException{
		log.info("手机注册信息：手机, 验证码, 密码", Arrays.asList(new String[]{phone,captcha,password}));
		
		Map<String, String> tempInfo = verifyCodeByPhone(phone, captcha);
		
		String areaCode = tempInfo.get("areaCode");
		String phoneTemp = tempInfo.get("phone");
		
		int length = password.length();
		// 密码安全等级
		byte passwordLevel = 0;
		if(length <= 12){
			passwordLevel = 1;
		}else if(length <= 16){
			passwordLevel = 2;
		}else{
			passwordLevel = 3;
		}
		
		// 对密码进行MD5加密
		password = CommonUtils.EncoderByMd5(password);
		// 创建用户基础信息对象		
        Date time = FixedTime.getCurrentTime();		
		UserBaseInfo userBaseInfo = new UserBaseInfo("", "", password, areaCode, phoneTemp, time, (byte)UserStatusConstant.USER_ACCOUNT_PHONE);
		Integer userId = userBaseInfoDao.saveUserBaseInfo(userBaseInfo);
		// 创建用户安全信息对象
		int loginAuthentication = appConfigDao.getAppConfigIntValue("loginAuthentication", 1);
		Date current = FixedTime.getCurrentTime();
		UserSafeInfo userSafeInfo = new UserSafeInfo(userId, "", "",(byte)UserStatusConstant.BIND_PHONE_YES, (byte)UserStatusConstant.SECURITY_LEVEL_PHONE, (byte)loginAuthentication,(byte)UserStatusConstant.AUTHEN_STATUS_INIT ,(byte)UserStatusConstant.USER_STATUS_ACTIVE, null, (byte)UserStatusConstant.LOCK_STATUS_NONE, 0, current, passwordLevel);
		userSafeInfoDao.saveUserSafeInfo(userSafeInfo);
		// 创建用户活动信息对象
		Date current1 = FixedTime.getCurrentTime();
		UserActivityInfo userActivityInfo = new UserActivityInfo(userId, (byte)1, 0, current1);
		userActivityInfoDao.saveUserActivityInfo(userActivityInfo);
		
		// 添加完成后将用户Id返回给前台用户
		return CollectionUtils.buildMap("userId", userId);
	}

	

	/**
	 * 邮箱注册
	 * @throws BusinessException 
	 * @throws EmailFailException 
	 */
	@SuppressWarnings("null")
	@Override
	public void emailRegister(String email) throws BusinessException, EmailFailException {
		// 1.根据邮箱统计使用该邮箱的人数
		int count = userBaseInfoDao.countUserByEmail(email);
		if(count > 0){
			log.error("US702", "The email has been used!");
			throw new BusinessException("US702","The email has been used!",null);
		}
		// 2.验证用户输入的验证码（错误提示、超限提示）
		Map<String, String> tempInfo = userRedisDao.getEmailRegisterTempInfo(email);
		if(null!=tempInfo || !tempInfo.isEmpty() || Integer.parseInt(tempInfo.get("emailMessageSendCount")+"") < emailMessageSendLimit){
			int emailMessageSendCount = 0;
			// 邮箱注册的临时信息存在
			if(null != tempInfo && !tempInfo.isEmpty()){
				emailMessageSendCount = Integer.parseInt(tempInfo.get("emailMessageSendCount") + "");
			}else{
				tempInfo = new HashMap<String,String>();
			}
			
			// 生成六位随机数的验证码
			String captcha = CommonUtils.randCode("", UserStatusConstant.CHECK_CODE_LENGTH);
			Map<String, Object> accessData = CollectionUtils.buildMap("email",email,"activeCode",captcha,"toEmail",email,"ctx",ctx);
			// 发送邮箱验证码
			//this.sendEmail(email, "active", 1, accessData, true);
			emailSendService.sendMessage(email, "emailRegister", true, accessData);
			tempInfo = CollectionUtils.buildMap("email",email,"captcha",captcha,"emailMessageSendCount",emailMessageSendCount+1+"","emailMessageVerifyCount","0","emailMessageSendTime",System.currentTimeMillis()+"");
			// 在Redis中保存邮件注册的临时信息
			userRedisDao.saveEmailRegisterTempInfo(tempInfo);
		}else{
			log.error("US619", "Email message delivery exceeds Limit");
			throw new BusinessException("US619", "Email message delivery exceeds " 
					+ emailMessageSendLimit + " limit!", null);
		}
	}

	/**
	 * 邮箱注册激活
	 * @throws BusinessException 
	 * 
	 */
	@Transactional
	@Override
	public Map<String, Object> activeEmail(String email, String captcha, String password) throws BusinessException {
		log.info("邮箱注册信息：邮箱, 验证码, 密码", Arrays.asList(new String[]{email,captcha,password}));
		
		Map<String, String> tempInfo = verifyCodeByEmail(email, captcha);
				
		String emailTemp = tempInfo.get("email");
		
		int length = password.length();
		// 密码安全等级
		byte passwordLevel = 0;
		if(length <= 12){
			passwordLevel = 1;
		}else if(length <= 16){
			passwordLevel = 2;
		}else{
			passwordLevel = 3;
		}
		
		// 对密码进行MD5加密
		password = CommonUtils.EncoderByMd5(password);
		// 创建用户基础信息对象
		Date time = FixedTime.getCurrentTime();	
		UserBaseInfo userBaseInfo = new UserBaseInfo("", emailTemp, password, "", "", time, (byte)UserStatusConstant.USER_ACCOUNT_EMAIL);
		int userId = userBaseInfoDao.saveUserBaseInfo(userBaseInfo);
		// 创建用户安全对象
		int loginAuthentication = appConfigDao.getAppConfigIntValue("loginAuthentication", 1); //登录认证
		Date current = FixedTime.getCurrentTime();
		UserSafeInfo userSafeInfo = new UserSafeInfo(userId, "", "", (byte)UserStatusConstant.BIND_PHONE_NO, (byte)UserStatusConstant.SECURITY_LEVEL_NONE, (byte)loginAuthentication,(byte)UserStatusConstant.AUTHEN_STATUS_INIT ,(byte)UserStatusConstant.USER_STATUS_ACTIVE, null,(byte)UserStatusConstant.LOCK_STATUS_NONE, 0, current, passwordLevel);
		userSafeInfoDao.saveUserSafeInfo(userSafeInfo);
		// 创建活动对象信息
		// 创建用户活动信息对象
		Date current1 = FixedTime.getCurrentTime();
		UserActivityInfo userActivityInfo = new UserActivityInfo(userId, (byte)1, 0, current1);
		userActivityInfoDao.saveUserActivityInfo(userActivityInfo);
		// 将用户Id返回给前台
		return CollectionUtils.buildMap("userId",userId);
	}

	/**
	 * 根据手机验证手机验证码
	 * @param phone
	 * @param captcha
	 * @return
	 * @throws BusinessException
	 */
	@Override
	public Map<String, String> verifyCodeByPhone(String phone, String captcha) throws BusinessException {
		// 在Redis中查询是否有手机号待激活
		UserBaseInfo user = userBaseInfoDao.getUserBaseInfoByAccount(phone);
		if(user != null){
			log.error("US652", "The phone has been used!");
			throw new BusinessException("US652","The phone has been used!", null);
		}
		
		// 从redis中获取手机注册的临时信息
		Map<String, String> tempInfo = userRedisDao.getPhoneRegisterTempInfo(phone);
		if(null == tempInfo){
			log.error("US653", "No phone needs to be activated!");
			throw new BusinessException("US653","No phone needs to be activated!", null);
		}
		
		Integer phoneMessageVerifyCount = Integer.parseInt(tempInfo.get("phoneMessageVerifyCount"));
		// phoneMessageVerifyLimit手机验证码验证次数限制5次
		if(phoneMessageVerifyCount >= phoneMessageVerifyLimit){
			log.error("US603", "Captcha verify exceeds Limit");
			throw new BusinessException("US603", "Captcha verify exceeds" + phoneMessageVerifyLimit + "limit!", null);
		}
		
		String captchaTemp = tempInfo.get("captcha");
		long sendTime = Long.parseLong(tempInfo.get("phoneMessageSendTime"));
		long currentTime = System.currentTimeMillis();
		// 手机验证码失效时间10分钟
		long captchaValidTime = RedisKeyUtils.getCaptchaValidTime();
		// 判断手机验证码是否失效
		if(currentTime - sendTime > captchaValidTime*1000){
			log.error("US604", "Captcha is invalid!");
			throw new BusinessException("US604", "Captcha is invalid!", null);
		}
		// 校验验证码
		if(!captcha.equals(captchaTemp)){
			String tempInfoKey = RedisKeyUtils.getPhoneRegisterTempInfoKey(phone);
			// 验证码验证次数增加
			userRedisDao.addVerifyCount(tempInfoKey);
			log.error("US605", "Captcha is error!");
			throw new BusinessException("US605", "Captcha is error!", null);
		}
		// 删除手机注册的临时信息
		userRedisDao.removePhoneRegisterTempInfo(phone);
		return tempInfo;
	}
	
	
	/**
	 * 根据邮箱验证邮箱验证码
	 * @param email
	 * @param captcha
	 * @return
	 * @throws BusinessException
	 */
	@Override
	public Map<String, String> verifyCodeByEmail(String email, String captcha) throws BusinessException {
		// 1.在redis中检测是否有账户待激活
		UserBaseInfo user = userBaseInfoDao.getUserBaseInfoByAccount(email);
		if(user != null){
			log.error("US702", "The email has been used!");
			throw new BusinessException("US702","The email has been used!", null);
		}
		
		// 2.从redis中获取邮箱注册的临时信息
		Map<String, String> tempInfo = userRedisDao.getEmailRegisterTempInfo(email);
		if(null == tempInfo || tempInfo.size() == 0){
			log.error("US706", "No email needs to be activated!");
			throw new BusinessException("US706","No email needs to be activated!", null);
		}
		
		Integer emailMessageVerifyCount = Integer.parseInt(tempInfo.get("emailMessageVerifyCount"));
		// 邮件验证码限制次数为5次
		if(emailMessageVerifyCount >= emailMessageVerifyLimit){
			log.error("US619", "Captcha verify exceeds Limit");
			throw new BusinessException("US619", "Captcha verify exceeds" + emailMessageVerifyLimit + "limit!", null);
		}
		
		String captchaTemp = tempInfo.get("captcha");
		long sendTime = Long.parseLong(tempInfo.get("emailMessageSendTime"));
		long currentTime = System.currentTimeMillis();
		// 邮件验证码失效时间10分钟
		long captchaValidTime = RedisKeyUtils.getCaptchaValidTime();
		// 判断邮件验证码是否失效
		if(currentTime - sendTime > captchaValidTime*1000){
			log.error("US604", "Captcha is invalid!");
			throw new BusinessException("US604", "Captcha is invalid!", null);
		}
		
		// 校验验证码
		if(!captcha.equals(captchaTemp)){
			String tempInfoKey = RedisKeyUtils.getPhoneRegisterTempInfoKey(email);
			// 验证码验证次数增加
			userRedisDao.addVerifyCount(tempInfoKey);
			log.error("US605", "Captcha is error!");
			throw new BusinessException("US605", "Captcha is error!", null);
		}
		// 删除邮箱注册的临时信息
		userRedisDao.removeEmailRegisterTempInfo(email);
		return tempInfo;
	}

	/**
	 * 发送手机短信【不对外】
	 * 
	 *//*
	@SuppressWarnings("unused")
	@Override
	public void sendMessage(final String areaCode, final String phone, final int systemId,final int moduleId, final String moudleName,
			final Map<String, Object> accessData, final boolean isSync) {
		// TODO Auto-generated method stub
		
		final JSONObject accessDataObj = JSONObject.fromObject(accessData);
		// 另起线程进行操作
		longTimeCallback.makeRemoteCallAndUnknowWhenFinish(new LongTimeTaskCallback(){

			@Override
			public void callback() {
				System.err.println("调用发送短信的接口");
				mobileMessService.sendMessage(phone, moudleName, isSync, accessData);
               // mobileMessService.sendMobileMessage(areaCode, phone, moudleName, accessDataObj.toString(), systemId+"", moduleId+"");
			}
			
		}, isSync);
			
		
	}*/
	
	/**
	 * 发送邮件
	 */
/*	@Override
	public void sendEmail(final String email, final String modelName, final int moduleId, 
			final Map<String,Object> accessData,final boolean isSync) {
		
		final JSONObject accessDataObj = JSONObject.fromObject(accessData);
		
		longTimeCallback.makeRemoteCallAndUnknowWhenFinish(new LongTimeTaskCallback() {
			@SuppressWarnings("unchecked")
			@Override
			public void callback() {
				try {
					System.err.println("调用发送邮件的接口");
					emailSendService.sendMessage(email, modelName, isSync, accessDataObj);
					// emailSendService.sendEmailByModule(email, modelName, 1 + "", moduleId + "", accessDataObj.toString());
				} catch (EmailFailException e) {    // 注意此处捕获的异常
					logger.error("email send error:" + email + "," + accessDataObj.toString());
					e.printStackTrace();
				}
			}
		} , isSync);
	}*/

}
